package com.gitee.huanminabc.utils_tools.redis.aspect.handler;

import com.gitee.huanminabc.utils_tools.redis.aspect.note.RedisDbSwitch;
import com.gitee.huanminabc.utils_tools.redis.config.RedisAutoConfiguration;
import com.gitee.huanminabc.utils_tools.redis.redisson.utils.RedissonUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * redis 数据源动态切换
 *
 * @Author: huanmin
 * @Date: 2022/8/8 11:45
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
@Aspect
@Component
public class RedisSwitchAspect implements InitializingBean {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private RedisAutoConfiguration redisAutoConfiguration;
    @Autowired
    private RedissonUtil redissonUtil;
    //当前线程的数据库
    public static ThreadLocal<Integer> dbIndex =null;
    @Override
    public void afterPropertiesSet()  {
        dbIndex=ThreadLocal.withInitial(() -> redisAutoConfiguration.getDbIndex());//初始化线程变量
    }

    //方法和类上的注解
    @Pointcut("@annotation(redisDbSwitch)|| @within(redisDbSwitch)")
    public void pointCut(RedisDbSwitch redisDbSwitch) {
    }

    @Around(value = "pointCut(redisDbSwitch)", argNames = "pjp,redisDbSwitch")
    public Object around(ProceedingJoinPoint pjp, RedisDbSwitch redisDbSwitch) throws Throwable {
        //判断是否是集群模式
        String model = redisAutoConfiguration.getModel();
        if ("cluster".equals(model)) {
            throw new RuntimeException("集群模式不支持切换redis数据库");
        }
        int db = redisDbSwitch.value();
        RedisSwitchAspect.dbIndex(db);//设置当前数据源索引
        Object proceed = null;
        try {
            proceed = pjp.proceed();
        } finally {
            RedisSwitchAspect.cleanThreadLocal();//清除线程变量

        }
        return proceed;
    }


    //清除线程变量
    public static void cleanThreadLocal() {
        if (RedisSwitchAspect.dbIndex.get() != null) {
            RedisSwitchAspect.dbIndex.remove();
        }
    }


    //手动切换当前redis放入的数据库 ,切换后的操作将在该数据库中进行,直到线程结束或者手动再次切换
    public static void dbIndex(int dbIndex) {
        RedisSwitchAspect.dbIndex.set(dbIndex);
    }


}
